﻿//========================================================= 
/**@file WinBluetoothTestLinker.h
 * @brief 
 * 
 * @date 2016-01-23   17:10:13
 * @author Zhyioo 
 * @version 1.0
 */ 
//--------------------------------------------------------- 
#ifndef _LIBZHOUYB_WINBLUETOOTHTESTLINKER_H_
#define _LIBZHOUYB_WINBLUETOOTHTESTLINKER_H_
//--------------------------------------------------------- 
#include "TestLinkerHelper.h"
#include "../../../include/BaseDevice.h"
#include "../../../include/Extension.h"
//--------------------------------------------------------- 
namespace zhou_yb {
namespace application {
namespace test {
//--------------------------------------------------------- 
/// 查找是否有指定地址的远程蓝牙设备
template<class TBluetoothDevice>
struct WinBluetoothAddressScanTestLinker : public TestLinker<TBluetoothDevice>
{
    /**
     * @brief 根据地址查找是否有指定的蓝牙设备
     * 
     * @param [in] dev 需要操作的设备
     * @param [in] arg 参数列表
     * - 参数:
     *  - Address : string 需要查找的蓝牙地址,格式为:"XX:XX:XX:XX:XX:XX"
     * .
     * @param [in] printer 信息输出器
     */
    virtual bool Link(TBluetoothDevice& dev, IStringArguments& arg, TextPrinter& printer)
    {
        // 枚举本地蓝牙 
        list_t<TBluetoothDevice::device_info> localdevlist;
        if(dev.EnumLocalDevice(localdevlist, true) < 1)
        {
            printer.TextPrint(TextPrinter::TextLogger, "没有识别到本地蓝牙设备");
            return false;
        }
        // 枚举所有的远程设备 
        list_t<TBluetoothDevice::device_info> devlist;
        list_t<BTH_ADDR> adrlist;

        // 开启蓝牙扫描
        list_t<TBluetoothDevice::device_info>::iterator localitr;
        for(localitr = localdevlist.begin();localitr != localdevlist.end(); ++localitr)
        {
            if(!(localitr->IsDiscoverable))
            {
                printer.TextPrint(TextPrinter::TextLogger, "开启蓝牙扫描...");
                TBluetoothDevice::EnableDiscovery(localitr->hRadio);
            }
            dev.EnumRemoteDevice(devlist, localitr->hRadio);
        }
        dev.WsaEnumRemoteDevice(devlist, &adrlist);
        // 没有枚举到设备 
        if(devlist.size() < 1)
        {
            printer.TextPrint(TextPrinter::TextLogger, "没有识别到远程蓝牙设备");
            return false;
        }
        list_t<TBluetoothDevice::device_info>::iterator itr;
        string sAdr = arg["Address"].To<string>();
        ByteArray bthAddress(sAdr.c_str(), sAdr.length());
        for(itr = devlist.begin();itr != devlist.end(); ++itr)
        {
            string adr = TBluetoothDevice::AddressToString(itr->Address);
            if(StringConvert::Contains(ByteArray(adr.c_str(), adr.length()), bthAddress, true))
            {
                return true;
            }
        }
        return false;
    }
};
//--------------------------------------------------------- 
/// 连接指定的蓝牙设备
template<class TBluetoothDevice>
struct WinBluetoothTestLinker : public TestLinker<TBluetoothDevice>
{
    /**
     * @brief 连接蓝牙设备
     * @date 2017-01-21 16:02
     * 
     * @param [in] dev 需要操作的设备
     * @param [in] arg 参数列表
     * - 参数:
     *  - Name : string 需要连接的蓝牙名称
     *  - Address : string 需要连接的蓝牙地址(和Name二选一)
     *  - ScanTimeout : uint 扫描蓝牙的超时时间(ms)
     *  - PIN : string 自动配对码
     *  - UUID : string 服务GUID
     *  - Port : uint [default:1] 连接蓝牙的端口号
     * .
     * @param [in] printer 输出器
     */
    virtual bool Link(TBluetoothDevice& dev, IStringArguments& arg, TextPrinter& printer)
    {
        string sName = arg["Name"].To<string>();
        uint scanTimeout = arg["ScanTimeout"].To<uint>(1000);

        dev.SetWaitTimeout(scanTimeout);

        BTH_ADDR btAdr = 0;
        HANDLE hLocalRadio = INVALID_HANDLE_VALUE;
        
        // 根据名称查找地址
        if(sName.length() > 0)
        {
            DevHelper::ErrEnum err = BluetoothDeviceHelper::ScanAddressByName<TBluetoothDevice>(dev, sName.c_str(), btAdr, hLocalRadio);
            if(err != DevHelper::EnumSUCCESS)
                return false;
        }
        const char* pUUID = NULL;
        string sUUID;
        if(arg.Get("UUID", sUUID))
            pUUID = sUUID.c_str();
        uint port = arg["Port"].To<uint>(1);

        const char* pPin = NULL;
        string sPin;
        if(arg.Get("PIN", sPin))
            pPin = sPin.c_str();
        // 打开设备
        if(!dev.Open(hLocalRadio, btAdr, pPin, pUUID, port))
            return false;

        TestLinkerHelper::LinkTimeoutBehavior(dev, arg, printer);
        if(!TestLinkerHelper::LinkCommand(dev, arg, printer))
        {
            dev.Close();
            return false;
        }
        return true;
    }
    /// 关闭设备
    virtual bool UnLink(TBluetoothDevice& dev, TextPrinter&)
    {
        dev.Close();
        return true;
    }
};
//--------------------------------------------------------- 
} // test
} // namespace application
} // namespace zhou_yb
//--------------------------------------------------------- 
#endif // _LIBZHOUYB_WINBLUETOOTHTESTLINKER_H_
//========================================================= 